package net.myspring.middle.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.myspring.common.mybatis.domain.Page;
import net.myspring.common.mybatis.domain.Pageable;
import net.myspring.common.utils.Collections3;
import net.myspring.common.utils.Const;
import net.myspring.common.utils.StringUtils;
import net.myspring.middle.domain.Menu;
import net.myspring.middle.domain.Permission;
import net.myspring.middle.mapper.MenuMapper;
import net.myspring.middle.mapper.PermissionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created by liuj on 16/7/10.
 */
@Service
public class MenuService {

    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private HttpSession httpSession;

    public Page<Menu> findPage(Pageable pageable, Map<String, Object> map) {
        Page<Menu> page = menuMapper.findPage(pageable, map);
        for (Menu menu : page.getContent()) {
            menu.setDeletable(getDeletable(menu));
        }
        return page;
    }

    public List<Menu> findTreeMenuList() {
        List<Menu> menus = Lists.newArrayList();
        List<Menu> sourceList = menuMapper.findAll();
        treeList(menus, sourceList, Const.ROOT_ID);
        return menus;
    }

    public List<Menu> findAll() {
        List<Menu> menus = Lists.newArrayList();
        List<Menu> sourceList = menuMapper.findAll();
        sortList(menus, sourceList, Const.ROOT_ID);
        for (Menu menu : menus) {
            String[] space = new String[menu.getParentIds().split(Const.CharEnum.COMMA.getValue()).length - Const.ROOT_PARENT_IDS.split(Const.CharEnum.COMMA.getValue()).length];
            Arrays.fill(space, Const.CharEnum.SPACE_FULL.getValue());
            menu.setFullName(StringUtils.join(space) + menu.getName().trim());
        }
        return menus;
    }

    public Menu findOne(String id) {
        return menuMapper.findOne(id);
    }

    @Transactional
    public Menu delete(Menu menu) {
        menu.setEnabled(false);
        menuMapper.update(menu);
        return menu;
    }

    @Transactional
    public Menu save(Menu menu) {
        menu.setIcon("fa fa-circle-o");
        if (menu.isCreate()) {
            menu.setParentIds(getParentIds(menu));
            menuMapper.save(menu);
        } else {
            menu.setParentIds(getParentIds(menu));
            menuMapper.update(menu);
        }
        return menu;
    }

    public List<Menu> findByType(Integer... types) {
        List<Integer> typeList = Lists.newArrayList(types);
        return menuMapper.findByTypes(typeList);
    }


    public boolean checkName(Menu menu) {
        Menu checkMenu = menuMapper.findByName(menu.getName());
        return checkMenu == null || checkMenu.getId().equals(menu.getId());
    }

    public boolean checkLink(Menu menu) {
        Menu checkMenu = menuMapper.findByLink(menu.getLink());
        return checkMenu == null || checkMenu.getId().equals(menu.getId());
    }

    public List<Menu> findMenuByAccount(String accountId) {
        List<Menu> menus = Lists.newArrayList();
        List<String> menuIds = permissionMapper.findMenuIdByAccountId(accountId);
        if (Collections3.isNotEmpty(menuIds)) {
            List<Menu> menuList = menuMapper.findByIds(menuIds);
            Set<String> menuIdSet = Sets.newHashSet();
            for (Menu menu : menuList) {
                menuIdSet.addAll(menu.getParentIdList());
            }
            menuIdSet.addAll(menuIds);
            List<Menu> sourceList = menuMapper.findByIds(new ArrayList<String>(menuIdSet));
            treeList(menus, sourceList, Const.ROOT_ID);
            menus = menus.get(0).getChildList();
        }
        return menus;
    }


    public String getMenuHtml(List<Menu> menus, String pageCode) {
        String ctx = httpSession.getServletContext().getContextPath();
        StringBuilder menuHtml = new StringBuilder();
        menuHtml.append("<li class='header'>菜单</li>");
        for (Menu menu : menus) {
            getChildMenuHtml(menu, menuHtml, pageCode, ctx);
        }
        return menuHtml.toString();
    }

    private String getChildMenuHtml(Menu menu, StringBuilder menuHtml, String pageCode, String ctx) {
        Menu activeMenu = null;
        List<String> parentIdList = Lists.newArrayList();
        if (pageCode != null) {
            activeMenu = menuMapper.findByCode(pageCode.trim());
            parentIdList = activeMenu.getParentIdList();
        }
        if (StringUtils.isNotEmpty(menu.getLink()) && !menu.getParentId().equals("1")) {
            if ((activeMenu != null && menu.getId().equals(activeMenu.getId())) || parentIdList.contains(menu.getId())) {
                menuHtml.append("<li class='active'><a href='" + ctx + menu.getLink() + "'><i class='" + menu.getIcon() + "'></i> <span>" + menu.getName() + "</span></a></li>");
            } else {
                menuHtml.append("<li><a href='" + ctx + menu.getLink() + "'><i class='" + menu.getIcon() + "'></i> <span>" + menu.getName() + "</span></a></li>");
            }
        } else {
            if ((activeMenu != null && parentIdList.contains(menu.getId()))) {
                menuHtml.append("<li class='treeview  active'> <a href='#'><i class='" + menu.getIcon() + "'></i> <span >" + menu.getName() + "</span><span class='pull-right-container'> <i class='fa fa-angle-left pull-right'></i></span></a> <ul class='treeview-menu'>");
            } else {
                menuHtml.append("<li class='treeview'> <a href='#'><i class='" + menu.getIcon() + "'></i> <span >" + menu.getName() + "</span><span class='pull-right-container'> <i class='fa fa-angle-left pull-right'></i></span></a> <ul class='treeview-menu'>");
            }
            for (Menu child : menu.getChildList()) {
                getChildMenuHtml(child, menuHtml, pageCode, ctx);
            }
            menuHtml.append("</ul> </li>");
        }
        return menuHtml.toString();
    }


    private Boolean getDeletable(Menu menu) {
        List<Permission> permissions = permissionMapper.findByMenuId(menu.getId());
        if (Collections3.isEmpty(permissions)) {
            return true;
        } else {
            return false;
        }
    }

    private void treeList(List<Menu> list, List<Menu> sourceList, String parentId) {
        for (int i = 0; i < sourceList.size(); i++) {
            Menu e = sourceList.get(i);
            if (e.getParentId().equals(parentId)) {
                list.add(e);
                // 判断是否还有子节点, 有则继续获取子节点
                for (int j = 0; j < sourceList.size(); j++) {
                    Menu child = sourceList.get(j);
                    if (child.getParentId().equals(e.getId())) {
                        treeList(e.getChildList(), sourceList, e.getId());
                        break;
                    }
                }
            }
        }
    }

    private void sortList(List<Menu> list, List<Menu> sourceList, String parentId) {
        for (int i = 0; i < sourceList.size(); i++) {
            Menu e = sourceList.get(i);
            if (e.getParentId().equals(parentId)) {
                list.add(e);
                // 判断是否还有子节点, 有则继续获取子节点
                for (int j = 0; j < sourceList.size(); j++) {
                    Menu child = sourceList.get(j);
                    if (child.getParentId().equals(e.getId())) {
                        sortList(list, sourceList, e.getId());
                        break;
                    }
                }
            }
        }
    }

    private String getParentIds(Menu menu) {
        String parentIds = "";
        Menu parent = menuMapper.findOne(menu.getParentId());
        parentIds = parent.getParentIds() + Const.CharEnum.COMMA.getValue() + parent.getId();
        return parentIds;
    }
}
